use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{Instruction, BytecodeReader, self}, rtda::{heap::Class, Frame}};


#[derive(Debug, Default)]
pub struct NEW {
    index: usize
}

impl Instruction for NEW {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u16() as usize;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        // 当前类的运行时常量池中找到一个类符号引用。
        let cp = frame.borrow().get_method().get_class().get_constant_pool().unwrap();
        let class_ref = cp.get_constant(self.index).unwrap().class_ref();
        // 解析这个类符号引用，拿到类数据
        let class = class_ref.lock().unwrap().resolved_class();
        
        // 类未初始化是先初始化
        if !class.init_started() {
            // 获取到此锁可进行初始化。
            let init_lock = class.get_init_lock();
            let _lock = init_lock.lock().unwrap();
            // TODO 231028 不清楚为什么不直接往下执行，而是在执行一次此指令，后续测试。
            // 当前帧的nextPC字段已经指向下一条指令，所以需要修改nextPC，让它重新指向当前指令。
            frame.borrow_mut().revert_next_pc();
            // 再次判断，若在其他线程初始化后获取到锁则跳过初始化
            if !class.init_started() {
                base::init_class(frame.borrow().get_thread(), class);
            }
            return;
        }
        // 接口和抽象类不能new
        if class.is_interface() || class.is_abstract() {
            panic!("java.lang.InstantiationError")
        }
        // 创建对象，并把对象引用推入栈顶
        let object = Box::into_raw(Box::new(Class::new_object(class)));
        frame.borrow().get_operand_stack().borrow_mut().push_ref(Some(object));
    }
    


}
